<?php
namespace PsiFramework\Classes\Util\Object;

use PsiFramework\Classes\Util\Manager\ApplicationManager;

/**
 * PsiFramework
 * Php Simple Framework
 *
 * @author Rémi San
 * @version beta
 */

/**
 * The EMail class represents an e-mail
 *
 * @package Util.Object
 */
class EMail
{

    protected /*string*/ $_to ;
    protected /*string*/ $_subject ;
    protected /*string*/ $_message ;
    protected /*string*/ $_from ;

    /**
     * Constructor
     *
     * @param     string    $to            the to adress
     * @param     string    $subject    the subject
     * @param     string    $message    the message
     * @param     string    $from        the from address
     * @return    EMail    instance
     */
    public function __construct(
        /*string*/ $from,
        /*string*/ $to,
        /*string*/ $subject,
        /*string*/ $message=null
    )
    {
        $this->_from = $from ;
        $this->_to = $to ;
        $this->_subject = $subject ;
        $this->_message = $message ;
    }

    public function getSubject()
    {
        return $this->_subject;
    }
    
    public function getMessage()
    {
        return $this->_message;
    }
    
    /**
     * Sends the message
     */
    public function send()
    {
        $to = '';
        
        if (is_array($this->_to)) {
            foreach ($this->_to as $t) {
                if (!isNullOrEmptyString($to)) $to .= ', ';
                $to .= $t;
            }      
        } else {
            $to = $this->_to;
        }
        
        if (isNullOrEmptyString($to)) {
            throw new \Exception('No recipient!');
        }
             
        $headers = 'From: ' . $this->_from . "\r\n" .
                   'Reply-To: ' . $this->_from . "\r\n" .
                   'X-Mailer: PHP/' . phpversion() . "\r\n" .
                   'Content-Type: text/html; charset=UTF-8' ;

        @mail($to, $this->_subject, $this->_message, $headers);
    }
    
    /**
     * 
     * @param array $globalMergeVarsArray
     * @param array $mergeVarsArray
     * 
     * @throws \Exception
     * 
     * @return \stdClass
     */
    public function sendWithMandrill($globalMergeVarsArray=null, $mergeVarsArray=null)
    {
        
        $mandrill = $this->getMandrill();
        $mandrillMessage = new \Mandrill_Messages($mandrill);
        $result = $mandrillMessage->send($this->getMandrillMessage($globalMergeVarsArray, $mergeVarsArray));
        
        return $this->processMandrillResult($result);
    }
    
    /**
     * 
     * @param string $templateName
     * @param array  $globalMergeVarsArray
     * @param array  $mergeVarsArray
     * 
     * @throws \Exception
     * 
     * @return \stdClass
     */
    public function sendWithMandrillTemplate($templateName, $globalMergeVarsArray=null, $mergeVarsArray=null)
    {
        
        $mandrill = $this->getMandrill();
        $mandrillMessage = new \Mandrill_Messages($mandrill);
        
        $result = null;
        $result = $mandrillMessage->sendTemplate($templateName, null, $this->getMandrillMessage($globalMergeVarsArray, $mergeVarsArray));
        
        return $this->processMandrillResult($result);
    }
    
    /**
     * 
     * @param mixed $recipient
     * 
     * @throws \Exception
     * 
     * @return \stdClass
     */
    protected static function getUser($recipient)
    {
        $to = new \stdClass();
        $to->email = null;
        $to->name = null;
        
        if (is_string($recipient)) {
            $to->email = $recipient;
        } else if (is_object($recipient)) {
            $to = $recipient;
        } else if (is_array($recipient) && array_key_exists('email', $recipient)) {
            $to->email = $recipient['email'];
            if (array_key_exists('name', $recipient)) {
                $to->name = $recipient['name'];
            }
        } else {
            throw new \Exception('Bad recipient format!');
        }
        
        return $to;
    }
    
    protected static function getVarObject($name, $content)
    {
        $vo = new \stdClass();
        $vo->name = $name;
        $vo->content = $content;
        
        return $vo;
    }
    
    protected static function getVarObjects($varsArray)
    {
        
        $vars  = array() ;
        
        if (!is_null($varsArray) && is_array($varsArray)) {
            foreach ($varsArray as $key => $value) {
                $vars[] = self::getVarObject($key, $value);
            }
        }
        
        return $vars;
    }
    
    protected static function getMergeVar($rcpt, $vars)
    {
        $mv = new \stdClass();
        $mv->{"rcpt"} = $rcpt;
        $mv->{"vars"} = self::getVarObjects($vars);
        
        return $mv;
    }
    
    protected static function getMergeVars($mergeVarsArray)
    {
        $mergeVars = array();
        
        if (!is_null($mergeVarsArray) && is_array($mergeVarsArray)) {
            foreach ($mergeVarsArray as $key => $value) {
                $mergeVars[] = self::getMergeVar($key, $value);
            }
        }
        
        return $mergeVars;
    }
    
    protected function getMandrill()
    {
        global $basePath;
        require_once($basePath.'/Plugins/Mandrill/Lib/Mandrill.php');
        
        $mandrillKey = ApplicationManager::getInstance()->getApplication()->getParameter('mandrillKey');
        
        return new \Mandrill($mandrillKey);
    }
    
    /**
     *
     * @param array $globalMergeVarsArray
     * @param array $mergeVarsArray
     * @param bool  $template
     *
     * @throws \Exception
     *
     * @return \stdClass
     */
    protected function getMandrillMessage($globalMergeVarsArray=null, $mergeVarsArray=null, /*bool*/ $template=false)
    {
        $message = new \stdClass();
    
        $to = array();
    
        if (is_array($this->_to)) {
            foreach ($this->_to as $t) {
                $to[] = self::getUser($t);
            }
        } else {
            $to[] = self::getUser($this->_to);
        }
    
        $from = self::getUser($this->_from);
    
        if (isNullOrEmptyString($from->email)) {
            throw new \Exception('No sender e-mail!');
        }
    
        if (count($to) == 0) {
            throw new \Exception('No recipient!');
        }
    
        $message = new \stdClass();
        if (!$template) {
            $message->{"html"} = $this->_message;
        }
        $message->{"subject"} = $this->_subject;
        $message->{"from_email"} = $from->email;
    
        if (!isNullOrEmptyString($from->name)) {
            $message->{"from_name"} = $from->name;
        }
    
        $message->{"to"} = $to;
    
        if (!is_null($globalMergeVarsArray)) {
            $message->{"global_merge_vars"} = self::getVarObjects($globalMergeVarsArray);
        }
    
        if (!is_null($mergeVarsArray)) {
            $message->{"merge_vars"} = self::getMergeVars($mergeVarsArray);
        }
    
        $message->{"track_opens"} = true;
        $message->{"track_clicks"} = true;
        $message->{"auto_text"} = true;
        $message->{"url_strip_qs"} = true;
        $message->{"preserve_recipients"} = true;
    
        return $message;
    }
    
    /**
     *
     * @param array $result
     *
     * @return \stdClass
     */
    protected function processMandrillResult(/*array*/ $result)
    {
        $allOk = true;
        if (!is_null($result) && is_array($result) && count($result) > 0) {
            foreach ($result as $emailResult) {
                if ($emailResult['status'] != 'sent') {
                    $allOk = false;
                }
            }
        } else {
            $allOk = false;
        }
    
        $response = new \stdClass();
        $response->status = $allOk;
        $response->details = $result;
    
        return $response;
    }
}
